package com.whately.core.base.config;

import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class MessageConverterConfig {


    class FastJsonHttpMessageConverterEx extends FastJsonHttpMessageConverter{

        private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();


        @Override
        public Object read(Type type, //
                           Class<?> contextClass, //
                           HttpInputMessage inputMessage //
        ) throws IOException, HttpMessageNotReadableException {
            String typeName = type.getTypeName();
            if (isFasterxml4Read(typeName)) {
                Object fasterxmlObjectNode = jackson2HttpMessageConverter.read(type,contextClass,inputMessage);
                return fasterxmlObjectNode;
            }else{
                return super.read(type,contextClass,inputMessage);
            }

        }

        private boolean isFasterxml4Read(String typeName){
            if(typeName!=null){
                if("com.fasterxml.jackson.databind.JsonNode".equals(typeName)||typeName.startsWith("com.fasterxml.jackson.databind.node.")){
                    return true;
                }
            }
            return false;
        }


        /*
         * @see org.springframework.http.converter.GenericHttpMessageConverter.write
         */
        @Override
        public void write(Object o, Type type, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
            String typeName = type.getTypeName();
            if (isFasterxml4Write(typeName)) {
                jackson2HttpMessageConverter.write(o,type,contentType,outputMessage);
            }else {
                super.write(o, contentType, outputMessage);// support StreamingHttpOutputMessage in spring4.0+
            }

        }

        private boolean isFasterxml4Write(String typeName){
            //com.fasterxml.jackson.databind.node.ObjectNode
            if(typeName!=null){
                if("com.fasterxml.jackson.databind.JsonNode".equals(typeName)||typeName.startsWith("com.fasterxml.jackson.databind.node.")){
                    return true;
                }
            }

            return false;
        }
    }


    /*
     * 使用fastJson
     */
    @Bean
    public HttpMessageConverter fastJsonHttpMessageConverter() {
        FastJsonConfig fastJsonConfig = new FastJsonConfig();

        //Long类型转String类型
        SerializeConfig serializeConfig = new SerializeConfig();
        // ToStringSerializer 是这个包 com.alibaba.fastjson.serializer.ToStringSerializer
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);


        //创建Fastjosn对象并设定序列化规则
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.PrettyFormat,
                SerializerFeature.DisableCircularReferenceDetect,// 避免循环引用
                SerializerFeature.WriteNullStringAsEmpty, // 将String类型的null转成""
                SerializerFeature.WriteMapNullValue,// 保留map空的字段
                SerializerFeature.WriteNullListAsEmpty, // 将List类型的null转成[]
                SerializerFeature.WriteDateUseDateFormat , //日期格式转换
                SerializerFeature.WriteNullBooleanAsFalse // 将Boolean类型的null转成false
        );

        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        fastJsonConfig.setCharset(StandardCharsets.UTF_8);
        //fastJsonConfig.setSerializeFilters(valueFilter);


        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverterEx();
        fastConverter.setDefaultCharset(StandardCharsets.UTF_8);


        // 中文乱码解决方案
        MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
        List<MediaType> mediaTypes = new ArrayList<>();
        // 支持 application/json;charset=UTF-8
        mediaTypes.add(mediaType);//设定json格式且编码为UTF-8
        // application/json 支持
        mediaTypes.add(MediaType.APPLICATION_JSON);

        //过期方法
        //mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);//设定json格式且编码为UTF-8
        fastConverter.setSupportedMediaTypes(mediaTypes);

        fastConverter.setFastJsonConfig(fastJsonConfig);
        return fastConverter;
    }


    /**
     * 使用gson，不使用 fastJson

     @Bean
     public HttpMessageConverters customHttpMessageConverters() {
     Collection<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
     GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();

     Gson gson = new GsonBuilder()
     .setDateFormat("yyyy-MM-dd HH:mm:ss")
     .setLongSerializationPolicy(LongSerializationPolicy.STRING)
     //序列化值为null的属性
     .serializeNulls()
     //处理swagger不兼容问题
     .registerTypeAdapter(Json.class, new SwaggerSpringfoxJsonToGsonAdapter())
     .create();
     gsonHttpMessageConverter.setGson(gson);

     messageConverters.add(gsonHttpMessageConverter);
     return new HttpMessageConverters(true, messageConverters);

     }
     */




}
